package com.chenzhou.qx.checklibrary;

import android.os.Build;
import android.util.Log;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

/**
 * Hook ActivityManager
 * @author tk
 * @date 2021/1/28
 */
public class HookActivityManager {

    private static final String TAG = "HookActivityManager";

    private static List<String> hookMethodNames = new ArrayList<String>() {{
        add("getRunningAppProcesses");
    }};

    public static void setHookList(List<String> list) {
        hookMethodNames = list;
    }

    public static void addHooks(String... hookNames) {
        if (hookNames != null && hookNames.length > 0) {
            for (int i = 0; i < hookNames.length; i++) {
                if (!hookMethodNames.contains(hookNames[i])) {
                    hookMethodNames.add(hookNames[i]);
                }
            }
        }
    }

    public static void hookIActivityManager() {
        try {
            //获取singleton成员字段
            Field singleton;
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
                singleton = Class.forName("android.app.ActivityManager").getDeclaredField("IActivityManagerSingleton");
            } else {
                singleton = Class.forName("android.app.ActivityManagerNative").getDeclaredField("gDefault");
            }
            singleton.setAccessible(true);
            //获取Singleton<IActivityManager> 实例
            Object singletonObj = singleton.get(null);
            Log.d(TAG, "singletonObj=" + singletonObj);

            //获取Singleton的mInstance字段
            Field mInstance = Class.forName("android.util.Singleton").getDeclaredField("mInstance");
            mInstance.setAccessible(true);

            //mInstance 就是IActivityManager的真实对象
            //获取IActivityManager真实对象
            final Object iam = mInstance.get(singletonObj);

            //代理IActivityManager
            Object proxy = Proxy.newProxyInstance(
                    Thread.currentThread().getContextClassLoader(),
                    new Class[]{Class.forName("android.app.IActivityManager")},
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            if (hookMethodNames.contains(method.getName())) {
                                Log.e(TAG, Log.getStackTraceString(new Throwable()));
                            }
                            return method.invoke(iam,args);
                        }
                    });

            mInstance.set(singletonObj, proxy);

            Log.d(TAG,"hook ActivityManager ok");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
